# -*- coding: utf-8 -*-
# created on 2016/9/23

from mathsolver.functions.base import *
from sympy.abc import x, y, a, b, t
from mathsolver.functions.zhixian.length import DianToXianJuLi2
from mathsolver.functions.zhixian.base import point_to_line_dis2
from sympy import solve, simplify
from mathsolver.functions.root.jiefangchen import JieFangChen
from mathsolver.functions.zhixian.property import GetZhongDian
from mathsolver.functions.zhixian.property import GetLiangDianJuLi
from mathsolver.functions.yuan.property import GetYuanCenterPoint, GetYuanNormalizedEq


# 根据圆心，半径求圆方程
class YuanFangCheng001(BaseFunction):
    """
    圆心为(1,-1),半径为2的圆的方程是()
    """
    def solver(self, *args):
        if len(args) == 1:
            name = BaseVariable("C").value
            yuanxin = self.search(name)
            yuanxin = yuanxin.sympify()
            banjing = args[0].sympify()
        elif len(args) == 3 and isinstance(args[0], BasePointName):
            name = args[0].sympify()
            yuanxin = args[1].sympify()
            banjing = args[2].sympify()
        else:
            name = ""
            yuanxin = args[0].sympify()
            banjing = args[1].sympify()
        self.steps.append(["", "∵圆心为%s, 半径为%s" % (
            BasePoint({"name": name, "value": [yuanxin[0], yuanxin[1]]}).printing(),
            BaseValue(banjing).printing())])
        eq = [(x - yuanxin[0]) ** 2 + (y - yuanxin[1]) ** 2, banjing ** 2]
        self.steps.append(["", "∴圆的方程为%s" % (BaseYuan({"name": name, "value": eq}).printing())])
        self.output.append(BaseYuan({"name": name, "value": eq}))
        self.label.add("根据圆心，半径求圆方程")
        return self


# 求解两圆的公共弦所在的直线
class TwoYuanCommonLine(BaseFunction):
    """
    圆x^{2}+y^{2}=50与圆x^{2}+y^{2}-12x-6y+40=0的公共弦长为()
    """
    def solver(self, *args):
        yibanshi1 = args[0].sympify()
        yibanshi2 = args[1].sympify()
        common_line = (yibanshi1[0] - yibanshi2[0]).factor()
        self.steps.append(["两式相减得两圆的公共弦长所在直线方程为:",
                           BaseZhiXian({"name": "", "value": [common_line, S.Zero]}).printing()])
        self.output.append(BaseZhiXian({"name": "", "value": [common_line, S.Zero]}))
        self.label.add("求解两圆的公共弦所在的直线")
        return self


# 圆外/上一点，求过该点与圆的切线
class PointQieYuan(BaseFunction):
    """
    圆x^{2}+y^{2}-4x=0在点P(1,\\sqrt{3})处的切线方程为()
    """
    def solver(self, *args):
        if len(args) == 5 and isinstance(args[4], BaseLineName):
            name = args[4].value
        elif len(args) == 5 and isinstance(args[4], BaseZhiXian):
            name = args[4].name
        else:
            name = ""
        guanxi = args[0].sympify()
        point = args[1].sympify()
        yuanxin = args[2].sympify()
        banjing = args[3].sympify()
        if guanxi == 1:
            eq = [a * (x - point[0]) + b * (y - point[1]), S.Zero]
            zhixian = BaseZhiXian({"name": name, "value": eq})
            self.steps.append(["", "设过(%s, %s)的直线方程为%s, 则" % (new_latex(point[0]), new_latex(point[1]), zhixian.printing())])
            juli = DianToXianJuLi2().solver(
                BasePoint({"name": name, "value": [yuanxin[0], yuanxin[1]]}), zhixian).output[0].value
            self.steps.append(["", "∴ %s" % (BaseEq([juli, banjing]).printing())])
            juli2 = point_to_line_dis2(BasePoint({"name": name, "value": [yuanxin[0], yuanxin[1]]}), zhixian)
            expr = juli2 - banjing ** 2
            symbol = list(expr.free_symbols)[0]
            answer = solve(expr, symbol)
            if len(answer) == 2:
                self.steps.append(["", "解得：%s = %s 或 %s = %s" % (new_latex(symbol), new_latex(answer[0]), new_latex(symbol), new_latex(answer[1]))])
                self.steps.append(["", "代入方程,并化简得"])
                eq_new1 = eq[0].subs({symbol: answer[0]})
                eq_new1 = simplify(eq_new1 / (list(eq_new1.free_symbols.difference([x, y]))[0]))
                eq_new2 = eq[0].subs({symbol: answer[1]})
                eq_new2 = simplify(eq_new2 / (list(eq_new2.free_symbols.difference([x, y]))[0]))
                self.steps.append(["", BaseZhiXian({"name": name, "value": [eq_new1, S.Zero]}).printing()])
                self.steps.append(["", BaseZhiXian({"name": name, "value": [eq_new2, S.Zero]}).printing()])
                self.output.append(BaseZhiXians([{"name": name, "value": [eq_new1, S.Zero]},
                                                 {"name": name, "value": [eq_new2, S.Zero]}]))
            self.label.add("过圆外一点求圆的切线方程")
        elif guanxi == 2:
            self.steps.append(
                ["", "因为%s在圆上,则" % (BasePoint({"name": name, "value": [point[0], point[1]]}).printing())])
            fa_vector = [point[0] - yuanxin[0], point[1] - yuanxin[1]]
            self.steps.append(["", "切线的法向量为%s" % (BaseVector({"name": name, "value": fa_vector}).printing())])
            eq = [fa_vector[0] * (x - point[0]) + fa_vector[1] * (y - point[1]), S.Zero]
            self.steps.append(["由点法向式得", BaseZhiXian({"name": name, "value": eq}).printing()])
            self.output.append(BaseZhiXian({"name": name, "value": eq}))
            self.label.add("过圆上一点求圆的切线方程")
        return self


# 过两点的圆系方程
class YuanFangCheng002(BaseFunction):
    """
    求过点A(1,-1),B(-1,1),圆心在直线x+y-2=0上的圆的方程.
    """
    def solver(self, *args):
        name = ""
        if len(args) == 1 and isinstance(args[0], (BasePoints, BaseMultiple)):
            points = args[0].sympify()
            point1 = points[0]
            point2 = points[1]
        elif len(args) == 2 and isinstance(args[1], (BasePoints, BaseMultiple)):
            name = args[0].name
            points = args[1].sympify()
            point1 = points[0]
            point2 = points[1]
        elif isinstance(args[1], BasePoints) and len(args) == 2:
            points = args[1].sympify()
            point1 = points[0]
            point2 = points[1]
        elif isinstance(args[1], BasePoint) and len(args) == 3:
            point1 = args[1].sympify()
            point2 = args[2].sympify()
        eq_left = (x - point1[0]) * (x - point2[0]) + (y - point1[1]) * (y - point2[1]) + t * ((x - point1[0]) * (point2[1] - point1[1]) - (y - point1[1]) * (point2[0] - point1[0]))
        self.steps.append(["", "设过%s和%s的圆系方程为%s" % (
            BasePoint({"name": "", "value": point1}).printing(),
            BasePoint({"name": "", "value": point2}).printing(),
            BaseYuan({"name": name, "value": [eq_left, S.Zero]}).printing())])
        new_eq_left = eq_left.expand().simplify()
        self.steps.append(["", "整理, 得"])
        self.steps.append(["", "%s" % BaseEq([new_eq_left, S.Zero]).printing()])
        self.output.append(BaseYuan({"name": name, "value": [new_eq_left, S.Zero]}))
        self.label.add("求过两点的圆系方程")
        return self


# 代入圆方程
class DaiRuYuanFangCheng(BaseFunction):
    def solver(self, *args):
        jies = args[0].sympify()
        symbol = None
        value = None
        for key, item in jies.items():
            symbol = key
            value = item.args[0]
        self.steps.append(["", "将%s代入方程得" % BaseEq([symbol, value]).printing()])
        yuan_name = args[1].name
        yuan_eq = args[1].sympify()
        new_left = yuan_eq[0].subs({symbol: value})
        new_left = new_left.expand().simplify()
        new_right = yuan_eq[1].subs({symbol: value})
        new_right = new_right.expand().simplify()
        new_yuan_eq = [new_left - new_right, S.Zero]
        self.steps.append(["", "%s" % BaseYuan({"name": yuan_name, "value": new_yuan_eq}).printing()])
        self.output.append(BaseYuan({"name": yuan_name, "value": new_yuan_eq}))
        self.label.add("代入方程")
        return self


# 求过点A(1,-1),B(-1,1),圆心在直线x+y-2=0上的圆的方程.
class YuanFangCheng003(BaseFunction):
    def solver(self, *args):
        name = args[0].value
        yuan = self.search(name)
        eq = args[1].sympify()
        step1 = GetYuanNormalizedEq().solver(yuan)
        self.steps += step1.steps
        self.label.update(step1.label)
        step2 = GetYuanCenterPoint().solver(step1.output[0])
        self.steps += step2.steps
        self.label.update(step2.label)
        yuanxin = step2.output[0].value
        self.steps.append(["", "因为圆心在直线%s上" % (
            BaseZhiXian({"name": "", "value": eq}).printing())])
        self.steps.append(["", "将圆心%s代入方程得" % (
            new_latex(BasePoint({"name": "", "value": yuanxin}).printing()))])
        new_eq_left = eq[0].subs({x: yuanxin[0], y: yuanxin[1]})
        new_eq_right = eq[1].subs({x: yuanxin[0], y: yuanxin[1]})
        self.steps.append(["", "%s" % BaseEq([new_eq_left, new_eq_right]).printing()])
        step2 = JieFangChen().solver(BaseEq([new_eq_left, new_eq_right]))
        self.steps += step2.steps
        jie = step2.output[0].value
        jie_keys = jie.keys()[0]
        answer = jie[jie_keys].args[0]
        yuan2 = yuan.sympify()
        new_yuan = [yuan2[0].subs({jie_keys: answer}), yuan2[1].subs({jie_keys: answer})]
        self.steps.append(["", "圆的方程为:%s" % (BaseYuan({"name": "", "value": new_yuan}).printing())])
        self.output.append(BaseYuan({"name": name, "value": new_yuan}))
        self.label.add("求圆的方程-其他型")
        return self


# 根据圆的直径求圆的方程:已知点A(-4,-5),B(6,-1),则以线段AB为直径的圆的方程为().
class YuanFangCheng004(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseLine):
            line_left, line_right = args[0].name
            point1 = self.search(line_left)
            point1 = point1.sympify()
            point2 = self.search(line_right)
            point2 = point2.sympify()
        yuanxin = GetZhongDian().solver(BasePoint({"name": "", "value": point1}), BasePoint({"name": "", "value": point2})).output[0].value
        self.steps.append(["", "圆心为%s" % (BasePoint({"name": "", "value": yuanxin}).printing())])
        juli = GetLiangDianJuLi().solver(BasePoint({"name": "", "value": point1}), BasePoint({"name": "", "value": point2})).output[0].value
        banjing = juli / 2
        self.steps.append(["", "半径为%s" % (new_latex(banjing))])
        eq = [(x - yuanxin[0]) ** 2 + (y - yuanxin[1]) ** 2, banjing ** 2]
        self.steps.append(["", "所以圆的方程为%s" % (BaseYuan({"name": "", "value": eq}).printing())])
        self.output.append(BaseYuan({"name": "", "value": eq}))
        self.label.add("根据圆的直径求圆的方程")
        return self


class YuanFangCheng005(BaseFunction):
    """
    求过三点A(1,12),B(7,10),C(-9,2)的圆的方程.
    """
    def solver(self, *args):
        points = args[0].sympify()
        point1_name, point2_name, point3_name = [obj.name for obj in args[0].objs]
        point1_value = points[0]
        point2_value = points[1]
        point3_value = points[2]
        name = ""
        if len(args) == 2:
            name = args[1].value

        eq_left = (x - point1_value[0]) * (x - point2_value[0]) + (y - point1_value[1]) * (y - point2_value[1]) + t * ((x - point1_value[0]) * (point2_value[1] - point1_value[1]) - (y - point1_value[1]) * (point2_value[0] - point1_value[0]))

        self.steps.append(["", "设过%s和%s的圆系方程为%s" % (
            BasePoint({"name": point1_name, "value": point1_value}).printing(),
            BasePoint({"name": point2_name, "value": point2_value}).printing(),
            BaseYuan({"name": name, "value": [eq_left, S.Zero]}).printing())])
        new_eqleft = eq_left.subs({x: point3_value[0], y: point3_value[1]})
        eq = [new_eqleft, S.Zero]
        self.steps.append(["将%s代入圆方程得" % (BasePoint({"name": point3_name, "value": point3_value}).printing()),
                           BaseEq(eq).printing()])
        stepsolver = JieFangChen().solver(BaseEq(eq))
        self.steps += stepsolver.steps
        jie = stepsolver.output[0].value
        target_symbol = list(jie.keys())[0]
        answer = jie[target_symbol].args[0]
        new_yuan = [eq_left.subs({target_symbol: answer}).expand().simplify(), S.Zero]
        self.steps.append(["将%s代入%s得" % (BaseEq([target_symbol, answer]).printing(), BaseEq(eq).printing()),
                           BaseYuan({"name": name, "value": new_yuan}).printing()])
        self.output.append(BaseYuan({"name": name, "value": new_yuan}))
        self.label.add("经过圆上三点求圆的方程")
        return self


if __name__ == '__main__':
    pass
